import { invoke } from '@tauri-apps/api/core';
import { useUIStore } from '../stores/uiStore';

// 错误类型定义
export interface AppError {
  code: string;
  message: string;
  details?: any;
  timestamp: number;
  stack?: string;
  context?: ErrorContext;
}

export interface ErrorContext {
  userId?: string;
  sessionId?: string;
  component?: string;
  action?: string;
  metadata?: Record<string, any>;
}

// 错误级别
export enum ErrorLevel {
  INFO = 'info',
  WARNING = 'warning',
  ERROR = 'error',
  CRITICAL = 'critical',
}

// 错误类别
export enum ErrorCategory {
  NETWORK = 'network',
  VALIDATION = 'validation',
  AUTHENTICATION = 'authentication',
  AUTHORIZATION = 'authorization',
  DATABASE = 'database',
  FILE_SYSTEM = 'file_system',
  SYSTEM = 'system',
  USER_INPUT = 'user_input',
  UNKNOWN = 'unknown',
}

// 错误处理配置
interface ErrorHandlerConfig {
  enableLogging: boolean;
  enableReporting: boolean;
  enableNotifications: boolean;
  logLevel: ErrorLevel;
  maxRetries: number;
  retryDelay: number;
}

class ErrorHandler {
  private config: ErrorHandlerConfig;
  private errorQueue: AppError[] = [];
  private retryQueue: Map<string, number> = new Map();

  constructor(config: Partial<ErrorHandlerConfig> = {}) {
    this.config = {
      enableLogging: true,
      enableReporting: true,
      enableNotifications: true,
      logLevel: ErrorLevel.ERROR,
      maxRetries: 3,
      retryDelay: 1000,
      ...config,
    };

    // 监听未捕获的错误
    this.setupGlobalErrorHandlers();
  }

  private setupGlobalErrorHandlers() {
    // 监听未捕获的 Promise 错误
    window.addEventListener('unhandledrejection', event => {
      this.handleError(
        this.createError(
          'UNHANDLED_PROMISE_REJECTION',
          event.reason?.message || 'Unhandled promise rejection',
          { reason: event.reason }
        )
      );
    });

    // 监听未捕获的 JavaScript 错误
    window.addEventListener('error', event => {
      this.handleError(
        this.createError('UNHANDLED_ERROR', event.message, {
          filename: event.filename,
          lineno: event.lineno,
          colno: event.colno,
          error: event.error,
        })
      );
    });
  }

  // 创建错误对象
  createError(
    code: string,
    message: string,
    details?: any,
    context?: ErrorContext
  ): AppError {
    return {
      code,
      message,
      details,
      timestamp: Date.now(),
      stack: new Error().stack,
      context,
    };
  }

  // 处理错误
  async handleError(error: AppError | Error | string, context?: ErrorContext) {
    let appError: AppError;

    if (typeof error === 'string') {
      appError = this.createError('GENERIC_ERROR', error, undefined, context);
    } else if (error instanceof Error) {
      appError = this.createError(
        error.name || 'ERROR',
        error.message,
        { stack: error.stack },
        context
      );
    } else {
      appError = { ...error, context: { ...error.context, ...context } };
    }

    // 添加到错误队列
    this.errorQueue.push(appError);

    // 记录错误
    if (this.config.enableLogging) {
      await this.logError(appError);
    }

    // 显示通知
    if (this.config.enableNotifications) {
      this.showErrorNotification(appError);
    }

    // 报告错误
    if (this.config.enableReporting) {
      await this.reportError(appError);
    }

    return appError;
  }

  // 记录错误到后端
  private async logError(error: AppError) {
    try {
      await invoke('add_log', {
        log: {
          level: this.getErrorLevel(error).toUpperCase(),
          message: `[${error.code}] ${error.message}`,
          component: error.context?.component || 'frontend',
          metadata: {
            error: error,
            context: error.context,
            details: error.details,
          },
        },
      });
    } catch (logError) {
      console.error('Failed to log error to backend:', logError);
    }
  }

  // 显示错误通知
  private showErrorNotification(error: AppError) {
    const { addNotification } = useUIStore.getState();

    const level = this.getErrorLevel(error);
    const notificationType = this.getNotificationType(level);

    addNotification({
      type: notificationType,
      title: this.getErrorTitle(error),
      message: this.getUserFriendlyMessage(error),
      duration: level === ErrorLevel.CRITICAL ? 0 : 5000,
    });
  }

  // 报告错误到外部服务
  private async reportError(error: AppError) {
    try {
      // 这里可以集成外部错误报告服务
      console.error('Error reported:', error);
    } catch (reportError) {
      console.error('Failed to report error:', reportError);
    }
  }

  // 获取错误级别
  private getErrorLevel(error: AppError): ErrorLevel {
    if (error.code.includes('CRITICAL') || error.code.includes('FATAL')) {
      return ErrorLevel.CRITICAL;
    }
    if (error.code.includes('WARNING') || error.code.includes('WARN')) {
      return ErrorLevel.WARNING;
    }
    if (error.code.includes('INFO')) {
      return ErrorLevel.INFO;
    }
    return ErrorLevel.ERROR;
  }

  // 获取通知类型
  private getNotificationType(
    level: ErrorLevel
  ): 'success' | 'error' | 'warning' | 'info' {
    switch (level) {
      case ErrorLevel.CRITICAL:
        return 'error';
      case ErrorLevel.ERROR:
        return 'error';
      case ErrorLevel.WARNING:
        return 'warning';
      case ErrorLevel.INFO:
        return 'info';
      default:
        return 'error';
    }
  }

  // 获取错误标题
  private getErrorTitle(error: AppError): string {
    const level = this.getErrorLevel(error);
    switch (level) {
      case ErrorLevel.CRITICAL:
        return '严重错误';
      case ErrorLevel.ERROR:
        return '错误';
      case ErrorLevel.WARNING:
        return '警告';
      case ErrorLevel.INFO:
        return '信息';
      default:
        return '错误';
    }
  }

  // 获取用户友好的错误消息
  private getUserFriendlyMessage(error: AppError): string {
    const errorMessages: Record<string, string> = {
      NETWORK_ERROR: '网络连接失败，请检查网络设置',
      VALIDATION_ERROR: '输入数据不符合要求',
      AUTHENTICATION_ERROR: '身份验证失败，请重新登录',
      AUTHORIZATION_ERROR: '您没有权限执行此操作',
      DATABASE_ERROR: '数据库操作失败',
      FILE_SYSTEM_ERROR: '文件操作失败',
      SYSTEM_ERROR: '系统错误，请稍后重试',
      USER_INPUT_ERROR: '输入数据有误，请检查后重试',
    };

    return errorMessages[error.code] || error.message || '发生了未知错误';
  }

  // 重试操作
  async retry<T>(
    operation: () => Promise<T>,
    errorCode: string,
    maxRetries?: number
  ): Promise<T> {
    const retries = maxRetries || this.config.maxRetries;
    const currentRetries = this.retryQueue.get(errorCode) || 0;

    try {
      const result = await operation();
      this.retryQueue.delete(errorCode);
      return result;
    } catch (error) {
      if (currentRetries < retries) {
        this.retryQueue.set(errorCode, currentRetries + 1);

        // 等待后重试
        await new Promise(resolve =>
          setTimeout(resolve, this.config.retryDelay * (currentRetries + 1))
        );

        return this.retry(operation, errorCode, maxRetries);
      } else {
        this.retryQueue.delete(errorCode);
        throw error;
      }
    }
  }

  // 获取错误历史
  getErrorHistory(): AppError[] {
    return [...this.errorQueue];
  }

  // 清除错误历史
  clearErrorHistory() {
    this.errorQueue = [];
    this.retryQueue.clear();
  }

  // 更新配置
  updateConfig(config: Partial<ErrorHandlerConfig>) {
    this.config = { ...this.config, ...config };
  }
}

// 创建全局错误处理器实例
export const errorHandler = new ErrorHandler();

// 便捷函数
export const handleError = (
  error: AppError | Error | string,
  context?: ErrorContext
) => {
  return errorHandler.handleError(error, context);
};

export const createError = (
  code: string,
  message: string,
  details?: any,
  context?: ErrorContext
) => {
  return errorHandler.createError(code, message, details, context);
};

export const retryOperation = <T>(
  operation: () => Promise<T>,
  errorCode: string,
  maxRetries?: number
) => {
  return errorHandler.retry(operation, errorCode, maxRetries);
};

// React Hook
export const useErrorHandler = () => {
  const handleError = (
    error: AppError | Error | string,
    context?: ErrorContext
  ) => {
    return errorHandler.handleError(error, context);
  };

  const createError = (
    code: string,
    message: string,
    details?: any,
    context?: ErrorContext
  ) => {
    return errorHandler.createError(code, message, details, context);
  };

  const retry = <T>(
    operation: () => Promise<T>,
    errorCode: string,
    maxRetries?: number
  ) => {
    return errorHandler.retry(operation, errorCode, maxRetries);
  };

  return {
    handleError,
    createError,
    retry,
    getErrorHistory: () => errorHandler.getErrorHistory(),
    clearErrorHistory: () => errorHandler.clearErrorHistory(),
  };
};

export default errorHandler;
